package utility.dates;

import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

public class MDate implements Comparable<MDate> {

	private GregorianCalendar _calendar;
	static public MDate from(int day, int month, int year) {		
		return new MDate(new GregorianCalendar(year,month-1,day));
	}

	static public MDate from(int day, int month, int year, int hour, int minute, int second) {
		return new MDate(new GregorianCalendar(year, month-1, day, hour, minute, second));
	}

	

	public MDate(GregorianCalendar calendar) {
		_calendar = calendar;
	}

	
	
	

	public String asDateString(String separator) {
		int dayAsInt = _calendar.get(Calendar.DAY_OF_MONTH);
		int monthAsInt = _calendar.get(Calendar.MONTH);
		
		String day = String.valueOf(dayAsInt);
		String month = String.valueOf(monthAsInt+1);
		String year = String.valueOf(_calendar.get(Calendar.YEAR));
		
		if(dayAsInt<10) day = "0"+day;
		if(monthAsInt<9) month = "0"+month;
		
		return day+separator+month+separator+year;
	}

	public String asDateAndTimeString(String dateSeparator, String timeSeparator) {
		String date = asDateString(dateSeparator);
		String time = asTimeString(timeSeparator);
		return date+" "+time;
	}

	public String asTimeString(String separator) {
		int hourAsInt = _calendar.get(Calendar.HOUR_OF_DAY);
		int minuteAsInt = _calendar.get(Calendar.MINUTE);
		int secondAsInt = _calendar.get(Calendar.SECOND);
		
		String hour = String.valueOf(hourAsInt);
		String minute = String.valueOf(minuteAsInt);
		String second = String.valueOf(secondAsInt);
		
		if(hourAsInt<10) hour = "0"+hour;
		if(minuteAsInt<10) minute = "0"+minute;
		if(secondAsInt<10) second = "0"+second;
		
		return hour+separator+minute+separator+second;
	}
	
	public Date utilsDate(){
		Date date = new Date(_calendar.getTimeInMillis());
		return date;
	}

	public static MDate now() {
		return new MDate(new GregorianCalendar());
	}

	public String asDottedString(boolean millisecond) {
		if (millisecond) return asDateAndPrecisionTimeString(".", ".", ".");
		return asDateAndTimeString(".", ".");
	}

	public static MDate from(int day, int month, int year, int hour, int minute, int second, int millisecond) {
		GregorianCalendar calendar = new GregorianCalendar(year, month-1, day, hour, minute, second);
		calendar.set(Calendar.MILLISECOND, millisecond);
		return new MDate(calendar);
	}

	public String asPrecisionTimeString(String timeSeparator, String millisecondSeparator) {
		String standardTime = asTimeString(timeSeparator);
		
		int millisecondAsInt = _calendar.get(Calendar.MILLISECOND);
		String millisecondAsString = String.valueOf(millisecondAsInt);
		if(millisecondAsInt<100) millisecondAsString = "0"+millisecondAsString;
		if(millisecondAsInt<10) millisecondAsString = "0"+millisecondAsString;
		
		return standardTime+millisecondSeparator+millisecondAsString;
	}

	public String asDateAndPrecisionTimeString(String dateSeparator, String timeSeparator, String millisecondSeparator) {
		String date = asDateString(dateSeparator);
		return date+" "+asPrecisionTimeString(timeSeparator, millisecondSeparator);
	}

	public void addSecond(int amount) {
		_calendar.add(GregorianCalendar.SECOND, amount);		
	}

	

	

	@Override
	public boolean equals(Object obj) {
		if (!(obj instanceof MDate)) return false;
		MDate toCompare = (MDate)obj;
		return ((toCompare._calendar.get(Calendar.YEAR)==_calendar.get(Calendar.YEAR))&&
				(toCompare._calendar.get(Calendar.MONTH)==_calendar.get(Calendar.MONTH))&&
				(toCompare._calendar.get(Calendar.DAY_OF_MONTH)==_calendar.get(Calendar.DAY_OF_MONTH))&&
				(toCompare._calendar.get(Calendar.HOUR_OF_DAY)==_calendar.get(Calendar.HOUR_OF_DAY))&&
				(toCompare._calendar.get(Calendar.MINUTE)==_calendar.get(Calendar.MINUTE))&&
				(toCompare._calendar.get(Calendar.SECOND)==_calendar.get(Calendar.SECOND))&&
				(toCompare._calendar.get(Calendar.MILLISECOND)==_calendar.get(Calendar.MILLISECOND))
				);
	}

	@Override
	public int hashCode() {
		return asDottedString(true).hashCode();
	}

	

	@Override
	public int compareTo(MDate date) {
		int yearComparation = _calendar.get(Calendar.YEAR)-date._calendar.get(Calendar.YEAR);
		int monthComparation = _calendar.get(Calendar.MONTH)-date._calendar.get(Calendar.MONTH);
		int dayComparation = _calendar.get(Calendar.DAY_OF_MONTH)-date._calendar.get(Calendar.DAY_OF_MONTH);
		int hourComparation = _calendar.get(Calendar.HOUR_OF_DAY)-date._calendar.get(Calendar.HOUR_OF_DAY);
		int minuteComparation = _calendar.get(Calendar.MINUTE)-date._calendar.get(Calendar.MINUTE);
		int secondComparation = _calendar.get(Calendar.SECOND)-date._calendar.get(Calendar.SECOND);
		int millisComparation = _calendar.get(Calendar.MILLISECOND)-date._calendar.get(Calendar.MILLISECOND);
		
		if (yearComparation!=0) return yearComparation;
		if (monthComparation!=0) return monthComparation;
		if (dayComparation!=0) return dayComparation;
		if (hourComparation!=0) return hourComparation;
		if (minuteComparation!=0) return minuteComparation;
		if (secondComparation!=0) return secondComparation;
		return millisComparation;
	}

	public static MDate fromMillis(long millis) {
		GregorianCalendar gregorianCalendar = new GregorianCalendar();
		gregorianCalendar.setTimeInMillis(millis);
		return new MDate(gregorianCalendar);
	}
	
	public static MDate fromUtilsDate(Date date){
		GregorianCalendar gregorianCalendar = new GregorianCalendar();
		gregorianCalendar.setTime(date);
		return new MDate(gregorianCalendar);
	}

	public int timeInSeconds() {
		return (int)(_calendar.getTimeInMillis()/1000);
	}

}
